/*
 * gdt.c
 * Copyright (c) 2010 Peter Polacik <polacik.p@gmail.com>
 *
 * This file is part of Beix Operating System
 *
 * Licensed under MIT License, see COPYRIGHT for more information.
 */

#include <beix.h>

struct gdt_entry {
	u16int limit_low;
	u16int base_low;
	u8int base_middle;
	u8int access;
	u8int granularity;
	u8int base_high;
} __attribute__((packed));

typedef struct gdt_entry gdt_entry_t;

struct gdt_ptr {
	u16int limit;
	u32int base;
} __attribute__ ((packed));

typedef struct gdt_ptr gdt_ptr_t;

gdt_entry_t gdt[3];
gdt_ptr_t gp;

extern void gdt_flush(void);

void gdt_set_gate(int num, unsigned long base, unsigned long limit, u8int access, u8int gran)
{
	gdt[num].base_low = (base & 0xFFFF);
	gdt[num].base_middle = (base >> 16) & 0xFF;
	gdt[num].base_high = (base >> 24) & 0xFF;
	
	gdt[num].limit_low = (limit & 0xFFFF);
	gdt[num].granularity = ((limit >> 16) & 0x0F);
	
	gdt[num].granularity |= (gran & 0xF0);
	gdt[num].access = access;
}

void gdt_install(void)
{
	gp.limit = (sizeof(gdt_entry_t) * 3) - 1;
	gp.base = &gdt;
	gdt_set_gate(0, 0, 0, 0, 0);
	gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
	gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
	gdt_flush();
}
